#include "PassThroughController.h"
#include <Limelight.h>

#undef LOG_DOMAIN
#undef LOG_TAG
#define LOG_DOMAIN  0x0
#define LOG_TAG     "TouchController"
#include <hilog/log.h>


namespace {
constexpr bool DEBUG = false;
}

PassThroughController::PassThroughController() {
}

PassThroughController::~PassThroughController() {
}

void PassThroughController::applyConfig(const std::unordered_map<std::string, std::string> &overrides) {
}

void PassThroughController::handle(OH_NativeXComponent *const comp, void *const win, const TouchEvent &touchEvent) {
    struct {
        uint64_t width;
        uint64_t height;
    } renderGeometry;
    if (auto res = OH_NativeXComponent_GetXComponentSize(comp, win, &renderGeometry.width, &renderGeometry.height); res != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
        OH_LOG_WARN(LOG_APP, "Failed to get XComponent size %{public}d", res);
        return;
    }
    if constexpr (DEBUG) {
        OH_LOG_DEBUG(LOG_APP, "Received touch event on xcomp %{public}dx%{public}d @ (%{public}f,%{public}f) with tool %{public}d",
            renderGeometry.width, renderGeometry.height, touchEvent.x, touchEvent.y, touchEvent.deviceId);
    }
    for (int p = 0; p < touchEvent.numPoints; p++) {
        const auto &point = touchEvent.touchPoints[p];
        if constexpr (DEBUG) {
            OH_LOG_DEBUG(LOG_APP, "Received touch event on xcomp %{public}dx%{public}d @ (%{public}f,%{public}f) of finger %{public}d type %{public}d",
                renderGeometry.width, renderGeometry.height, point.x, point.y, point.id, point.type);
        }
        uint8_t eventType = LI_TOUCH_EVENT_CANCEL;
        switch (point.type) {
            case OH_NATIVEXCOMPONENT_DOWN: { eventType = LI_TOUCH_EVENT_DOWN; break; }
            case OH_NATIVEXCOMPONENT_UP: { eventType = LI_TOUCH_EVENT_UP; break; }
            case OH_NATIVEXCOMPONENT_MOVE: { eventType = LI_TOUCH_EVENT_MOVE; break; }
            case OH_NATIVEXCOMPONENT_CANCEL: { eventType = LI_TOUCH_EVENT_CANCEL; break; }
            default: {
                OH_LOG_WARN(LOG_APP, "Unrecognized touch event type %{public}d", point.type);
                continue;
            }
        }
        OH_NativeXComponent_TouchPointToolType toolType = OH_NATIVEXCOMPONENT_TOOL_TYPE_UNKNOWN;
        if (auto res = OH_NativeXComponent_GetTouchPointToolType(comp, point.id, &toolType); res != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
            OH_LOG_WARN(LOG_APP, "Failed to get touch tool type %{public}d", res);
        }
        switch (toolType) {
            case OH_NATIVEXCOMPONENT_TOOL_TYPE_FINGER: {
                if (auto liRes = LiSendTouchEvent(
                        eventType, point.id,
                        1. * point.x / renderGeometry.width,
                        1. * point.y / renderGeometry.height,
                        /*pressureOrDistance=*/point.force,
                        /*contactAreaMajor=*/0, /*contactAreaMinor=*/0, /*rotation=*/0); liRes != 0) {
                    OH_LOG_WARN(LOG_APP, "Failed to send touch event %{public}d", liRes);
                }
                break;
            }
            // TODO pen event
            default: {
                OH_LOG_WARN(LOG_APP, "Unhandled touch point type %{public}d", toolType);
                continue;
            }
        }
    }
}
